/*******************************************************************************
 * Copyright 2013 Mindaugas Idzelis
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package incontrol.bf3.protocol.events.datatype;

import static com.google.common.collect.Lists.newArrayList;

import java.util.Collections;
import java.util.List;

import com.google.common.base.Objects;
import com.google.common.net.HostAndPort;

public class ServerInfo {

	public final String serverName;
	public final int currentPlayerCount;
	public final int maxPlayerCount;
	public final GameMode gamemode;
	public final BF3Map map;
	public final int roundsPlayed;
	public final int roundsTotal;
	public final TeamScores teamScores;
	public final boolean online;
	public final boolean ranked;
	public final boolean punkBuster;
	public final boolean hasPassword;
	public final int uptime;
	public final int roundTime;
	public final HostAndPort host;
	public final String punkBusterVersion;
	public final boolean hasJoinQueue;
	public final String region;
	public final String pingSite;
	public final String country;
	public final boolean matchmaking;

	public ServerInfo(String serverName, int currentPlayerCount,
			int maxPlayerCount, GameMode gamemode, BF3Map map,
			int roundsPlayed, int roundsTotal, TeamScores teamScores,
			boolean online, boolean ranked, boolean punkBuster,
			boolean hasPassword, int uptime, int roundTime, HostAndPort host,
			String punkBusterVersion, boolean hasJoinQueue, String region,
			String pingSite, String country, boolean matchmaking) {
		super();
		this.serverName = serverName;
		this.currentPlayerCount = currentPlayerCount;
		this.maxPlayerCount = maxPlayerCount;
		this.gamemode = gamemode;
		this.map = map;
		this.roundsPlayed = roundsPlayed;
		this.roundsTotal = roundsTotal;
		this.teamScores = teamScores;
		this.online = online;
		this.ranked = ranked;
		this.punkBuster = punkBuster;
		this.hasPassword = hasPassword;
		this.uptime = uptime;
		this.roundTime = roundTime;
		this.host = host;
		this.punkBusterVersion = punkBusterVersion;
		this.hasJoinQueue = hasJoinQueue;
		this.region = region;
		this.pingSite = pingSite;
		this.country = country;
		this.matchmaking = matchmaking;
	}

	public static ServerInfo parse(String[] words) {
		int wordCur = 0;
		String serverName = words[wordCur++];
		int curPlayer = Integer.parseInt(words[wordCur++]);
		int maxPlayer = Integer.parseInt(words[wordCur++]);
		GameMode game = GameMode.lookup(words[wordCur++]);
		BF3Map map = BF3Map.lookup(words[wordCur++]);
		int roundsPlayed = Integer.parseInt(words[wordCur++]);
		int roundsTotal = Integer.parseInt(words[wordCur++]);
		TeamScores ts = new TeamScores(Collections.<Integer> emptyList(), 0);
		boolean online = false;
		int numTeams = 0;
		try {
			// curious, when numTeams == null, then the online boolean is not
			// sent at all
			numTeams = Integer.parseInt(words[wordCur++]);

			List<Integer> teamScores = newArrayList();
			for (int i = 0; i < numTeams; i++) {
				teamScores.add((int) Double.parseDouble(words[wordCur++]));
			}

			int goalScore = 0;
			try {
				Integer.parseInt(words[wordCur++]);
			} catch (Exception e) {
				// ignore
			}
			ts = new TeamScores(teamScores, goalScore);

			online = Boolean.parseBoolean(words[wordCur++]);
		} catch (Exception e) {
			// ignore - between rounds, this value is ""
		}

		boolean ranked = Boolean.parseBoolean(words[wordCur++]);
		boolean hasPunkBuster = Boolean.parseBoolean(words[wordCur++]);
		boolean hasPassword = Boolean.parseBoolean(words[wordCur++]);
		int uptime = Integer.parseInt(words[wordCur++]);
		int roundtime = Integer.parseInt(words[wordCur++]);
		HostAndPort host = HostAndPort.fromString(words[wordCur++]);
		String punkBusterVer = words[wordCur++];
		boolean hasJoinQueue = Boolean.parseBoolean(words[wordCur++]);
		String region = words[wordCur++];
		String pingSite = words[wordCur++];
		String country = words[wordCur++];
		boolean matchmaking = Boolean.parseBoolean(words[wordCur++]);

		return new ServerInfo(serverName, curPlayer, maxPlayer, game, map,
				roundsPlayed, roundsTotal, ts, online, ranked, hasPunkBuster,
				hasPassword, uptime, roundtime, host, punkBusterVer,
				hasJoinQueue, region, pingSite, country, matchmaking);
	}

	@Override
	public String toString() {
		return Objects.toStringHelper(this).add("serverName", serverName)
				.add("currentPlayerCount", currentPlayerCount)
				.add("maxPlayerCount", maxPlayerCount)
				.add("gamemode", gamemode).add("map", map)
				.add("roundsPlayed", roundsPlayed)
				.add("roundsTotal", roundsTotal).add("teamScores", teamScores)
				.add("online", online).add("ranked", ranked)
				.add("punkBuster", punkBuster).add("hasPassword", hasPassword)
				.add("uptime", uptime).add("roundTime", roundTime)
				.add("host", host).add("punkBusterVersion", punkBusterVersion)
				.add("hasJoinQueue", hasJoinQueue).add("region", region)
				.add("pingSite", pingSite).add("country", country)
				.add("matchmaking", matchmaking).toString();
	}

	public String getServerName() {
		return serverName;
	}

	public int getCurrentPlayerCount() {
		return currentPlayerCount;
	}

	public int getMaxPlayerCount() {
		return maxPlayerCount;
	}

	public GameMode getGamemode() {
		return gamemode;
	}

	public BF3Map getMap() {
		return map;
	}

	public int getRoundsPlayed() {
		return roundsPlayed;
	}

	public int getRoundsTotal() {
		return roundsTotal;
	}

	public TeamScores getTeamScores() {
		return teamScores;
	}

	public boolean isOnline() {
		return online;
	}

	public boolean isRanked() {
		return ranked;
	}

	public boolean isPunkBuster() {
		return punkBuster;
	}

	public boolean isHasPassword() {
		return hasPassword;
	}

	public int getUptime() {
		return uptime;
	}

	public int getRoundTime() {
		return roundTime;
	}

	public HostAndPort getHost() {
		return host;
	}

	public String getPunkBusterVersion() {
		return punkBusterVersion;
	}

	public boolean isHasJoinQueue() {
		return hasJoinQueue;
	}

	public String getRegion() {
		return region;
	}

	public String getPingSite() {
		return pingSite;
	}

	public String getCountry() {
		return country;
	}

	public boolean isMatchmaking() {
		return matchmaking;
	}

}
